在昨天有介紹到 Server Components 是沒有辦法互動的,這時候就需要搭配 Client Component 來互動了。要在 Client Component 使用 Server Component,Server Component 必須用 children props 的方式傳入。
使用範例:
import ClientComponent from "./client-component";
import ServerComponent from "./server-component";
export default function App() {
return (
<ClientComponent>
<ServerComponent />
</ClientComponent>
);
}
"use client"
當有使用 React Server Component 或相容的 library 時,才需要使用到
"use client"
。
"use client"
用來標記在 client 端運行的程式碼,使用方式是必須放在檔案的最開頭, 在 import
的內容和其他程式碼上方。
"use client"
指令可以當作 client 和 server 的邊界。這個邊界是根據模組依賴關係樹 (module dependency tree)來建立,而不是依據渲染樹(render tree)。
所以即使某個元件在結構上具有父子關係,也並不代表它們會在相同的渲染環境中運行。
另外在 Client Components render 之前,Server Components 就已經 render 完成。
圖片說明:
在預設情況下,元件會被當作 Server Components。如果元件有使用 "use client"
指令在模組中定義的,或者元件是在 Client Component 中被 import
的,都會被當作 Client Components。
在上方的範例中,App
、FancyText
和 Copyright
都是 Server Components,而 InspirationGenerator
和底下被 import
的元件會是 Client Components。
所以一個 Component 可以是 Server Components,也可以是 Client Components。某個元件是否為 Client Component,取決於被使用方式。像 FancyText
就是一個例子。
要注意的是這邊的 Server Components 僅限於沒有使用 server 功能的元件(不需要等待資料的),如果是 Async Components 的話直接 import
到 Client Component 中會出現錯誤,必須用 children props 的方式傳入。
當我們在 Client Components 中使用 Server Components 時,透過 props
可以將資料從父元件傳遞到子元件。但因為 Server Components 和 Client Components 是在不同的環境中渲染,傳遞 props
會有一些限制。傳遞的 props
必須是 可序列化的 (serializable) 或 React Components,才能成功傳遞到 Client Component。
可序列化的 props 包括:Primitives(如 string、number)、可序列化的物件(如 Array、Map、Set)、日期(Date)、Client 或 Server Component 的元素(JSX)、Server Actions 的函式、Promise 等。
更多詳細內容可以參考 React 文件。
"use server"
和 Server Functions另一個相似的指令是 "use server"
,不過 "use server"
不是用在 Server Component 中,而是用在 Server Functions。
一樣是當有使用 React Server Component 或相容的 library 時,才需要使用到
"use server"
。
透過 Server Functions (之前叫 Server Actions),可以在 Client 端執行某些操作時,將請求發送到 Server 端進行處理,通常是用於與資料庫、API 等後端服務互動。而 "use server"
用來標記可以從 Client 端調用的 server-side function。另外使用 "use server"
標記的函式必須是非同步的(async),因為 Server Actions 的底層實現是依賴於非同步網路請求。
"use server"
只能在 Server 端的檔案中使用,不能在 Client 端的程式碼中使用。使用方式有兩種,一種是在 Server Component 中建立,另一種直接建立在獨立的檔案中。
"use server"
必須放在 async function 的最上方。import Button from "./Button";
function EmptyNote() {
async function createNoteAction() {
"use server";
await db.notes.create();
}
return <Button onClick={createNoteAction} />;
}
"use server"
必須放在檔案的最上方,位於 import
和其他程式碼上方"use server";
export async function create() {
// 調用 database 或其他 server-side 相關邏輯
}
其他更多 Server Functions 相關的內容,會在明天的文章說明。
參考資料:
https://react.dev/reference/rsc/server-components#adding-interactivity-to-server-components
https://react.dev/reference/rsc/use-client#building-with-interactivity-and-state
https://react.dev/reference/rsc/server-action
https://react.dev/reference/rsc/use-server
https://ithelp.ithome.com.tw/articles/10317180